package Module::CPANTS::Kwalitee::FindModules;
use warnings;
use strict;
use Data::Dumper;
sub order { 30 }

##################################################################
# Analyse
##################################################################

sub analyse {
    my $class=shift;
    my $me=shift;
    my $files=$me->d->{files_array};
   
# don't use META.yml's provides, because it lists every package defined in
# the files, which leads to strange results.
#    # use provides (META.yml) if available
#    my $meta=$me->d->{meta_yml};
#    if (my $provides=$meta->{provides}) {
#        while (my ($module,$data)=each %$provides) {
#            my $where='unknown';
#            if ($data->{file} =~ m|lib/|) {
#                $where='lib';
#            }
#            elsif ($data->{file} !~ m|/|) {
#                $where='base';
#            }
#            
#            push(@{$me->d->{modules}},
#                {
#                    module=>$module,
#                    file=>$data->{file},
#                    in_basedir=>$where eq 'base' ? 1 : 0,
#                    in_lib=> $where eq 'lib' ? 1 : 0,
#                });
#        }
#        return;
#    }
    
    my @modules_basedir=grep {/^[^\/]+\.pm$/} @$files;
    if (@modules_basedir) {
        my $namespace=$me->d->{dist} || die 'unknown namespace '.Dumper($me);
        
        # try to guess the namespace
        if ($namespace=~/-/) {
            # multi-level namespace
            $namespace=~s/-[^-]+$/-/;    # remove last part of name
            $namespace=~s/-/::/g;
        }
        
        # single level namespace (e.g. 'threads')
        else {
            $namespace='';    
        }
        foreach my $file (@modules_basedir) {
            my $module=$namespace.$file;
            $module=~s/\.pm$//;
            push(@{$me->d->{modules}},
                {
                    module=>$module,
                    file=>$file,
                    in_basedir=>1,
                    in_lib=>0,
                });
        }
    }

    if ($me->d->{dir_lib} == 1) {
        my @modules_path;
        foreach my $file (@$files) {
            next unless $file=~m|^lib/(.*)\.pm$|;
            my $module=$1;
            $module=~s|/|::|g;
            push (@{$me->d->{modules}},
                {
                    module=>$module,
                    file=>$file,
                    in_basedir=>0,
                    in_lib=>1,
                });
        }
    }

    if (!@modules_basedir && !$me->d->{dir_lib}) {
        my @modules_path;
        foreach my $file (@$files) {
            next unless $file=~/\.pm$/;
            next if $file=~m{/t/};
            next if $file=~m{/test/};
            next if $file=~m{/inc/};   # skip Module::Install stuff
            $file=~m|(.*)\.pm$|;
            my $module=$1;
            $module=~s|^[a-z]+/||;  # remove lowercase prefixes which most likely are not part of the distname (but something like 'src/')
            $module=~s|/|::|g;

            push(@{$me->d->{modules}},
                {
                    module=>$module,
                    file=>$file,
                    in_basedir=>0,
                    in_lib=>0,
                });
        }
    }
    
    return 1;
}



##################################################################
# Kwalitee Indicators
##################################################################

sub kwalitee_indicators {
    return [
        {
            name=>'proper_libs',
            error=>q{There is more than one .pm file in the base dir, or the .pm files are not in directory lib.},
            remedy=>q{Move your *.pm files in a directory named 'lib'. The directory structure should look like 'lib/Your/Module.pm' for a module named 'Your::Module'.},
            code=>sub { 
                my $d=shift;
                my $modules=$d->{modules};
                return 0 unless $modules;

                my @in_basedir=grep { $_->{in_basedir} } @$modules;
                return 1 if $d->{dir_lib} && @in_basedir == 0;
                return 1 if @in_basedir == 1;
                return 0;
            },
        },
    ];
}


q{Favourite record of the moment:
  Fat Freddys Drop: Based on a true story};


__END__

=pod

=head1 NAME

Module::CPANTS::Kwalitee::FindModules - Find modules provided by a dist

=head1 SYNOPSIS

Finds and reports all modules (i.e. F<*.pm> files) in a distribution.

=head1 DESCRIPTION

=head2 Methods

=head3 order

Defines the order in which Kwalitee tests should be run.

Returns C<30>, as data generated by C<MCK::FindModules> is used by other tests.

=head3 analyse

C<MCK::FindModules> first looks in C<basedir> and F<lib/> for C<*.pm> files. If it doesn't find any, it looks in the whole dist, but the C<proper_libs> kwalitee point is only awarded if the modules are F<lib/> or there's only one module in C<basedir>.

=head3 kwalitee_indicators

Returns the Kwalitee Indicators datastructure.

=over

=item * proper_libs

=back

=head1 SEE ALSO

L<Module::CPANTS::Analyse>

=head1 AUTHOR

Thomas Klausner, <domm@cpan.org>, http://domm.zsi.at

=head1 COPYRIGHT

You may use and distribute this module according to the same terms
that Perl is distributed under.

=cut
